﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Configuration;
using System.Net;
using System.Threading;
using Common.Models;


namespace StockClientUI
{


    public delegate void OnRecivedMsgDelegate(string msg);
    public delegate void OnError(string errorMsg);
    public class ClientConnector
    {

        public event OnRecivedMsgDelegate RecivedMsgEvt = null;

        public event OnError ErrorEvt = null;


        private ManualResetEvent connectDone = new ManualResetEvent(false);
        private ManualResetEvent sendDone = new ManualResetEvent(false);
        private ManualResetEvent receiveDone = new ManualResetEvent(false);

        Socket m_Socket;

        string ConnectAddress
        {
            get
            {
                return ConfigurationManager.AppSettings["ServerIPAndPort"];
            }
        }

        ClientConnector()
        {


        }

        public void Init()
        {
            m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            string[] address = ConnectAddress.Split(':');
            try
            {
                IPEndPoint ipAddress = new IPEndPoint(IPAddress.Parse(address[0]), int.Parse(address[1]));

                m_Socket.Connect(ipAddress);
                //m_recieveThread = new Thread(new ThreadStart(Receive));
                //m_recieveThread.Start();
                Receive();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                if (ErrorEvt != null)
                {
                    ErrorEvt("连接失败");
                }
            }
        }

        Thread m_recieveThread;

        private void SendCallback(IAsyncResult ar)
        {
            try
            {
                Socket client = (Socket)ar.AsyncState;
                int bytesSent = client.EndSend(ar);
                Console.WriteLine("收到发送回信");

                sendDone.Set();
            }
            catch (Exception e)
            {
                Console.WriteLine("发送回信失败" + e.ToString());
                Console.WriteLine(e.ToString());
            }
        }

        private void Receive()
        {

            try
            {
                Console.WriteLine("开始接收");
                StateObject state = new StateObject();
                state.workSocket = m_Socket;
                m_Socket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
                //  connectDone.WaitOne();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }




        private void ConnectCallback(IAsyncResult ar)
        {
            try
            {

                Socket client = (Socket)ar.AsyncState;
                client.EndConnect(ar);

                connectDone.Set();
            }
            catch (Exception ex)
            {
                ex.GetBaseException();
            }
        }




        static Thread getreceive;
        private string response = String.Empty;

        private void ReceiveCallback(IAsyncResult ar)
        {

            try
            {

                StateObject state = (StateObject)ar.AsyncState;
                Socket client = state.workSocket;

                if (client.Connected)
                {
                    int bytesRead = client.EndReceive(ar);
                    if (bytesRead > 0)
                    {
                        string msg = Encoding.GetEncoding("GB2312").GetString(state.buffer, 0, bytesRead);
                        ProcessRecieveMsg(msg, client);
                        Console.WriteLine("读到服务器响应" + msg);

                        Console.WriteLine("再次开始异步接收");
                        client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
                        //response = state.sb.ToString();
                        // 处理回发消息

                        if (RecivedMsgEvt != null)
                        {
                            RecivedMsgEvt(response);
                        }
                        //if (response.Contains("#"))
                        //{
                        //    getreceive = new Thread(new ThreadStart(ProcessLogin));
                        //    getreceive.Start();
                        //}

                    }
                    else
                    {
                        if (state.sb.Length > 1)
                        {
                            response = state.sb.ToString();
                        }

                        receiveDone.Set();
                    }
                }
                else
                {
                    Console.WriteLine("套接字已关闭");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

        }

        private void ProcessRecieveMsg(string msg, Socket client)
        {
            string[] msges = msg.Split('|');
            if (msges != null && msges.Length > 0)
            {
                MsgType type = (MsgType)int.Parse(msges[0]);
                switch (type)
                {
                    case MsgType.Login:
                        ProcessLogin(client, msges[1], msges[2]);
                        break;
                    case MsgType.Exit:
                        ProcessExit(client, msges[1]);
                        break;
                    default:
                        ProcessOther(msg);
                        break;
                }
            }
        }

        private void ProcessExit(Socket client, string p)
        {

        }

        private void ProcessOther(string msg)
        {
            Console.WriteLine(string.Format("接收到来自服务器的其它消息:{0}", msg));
        }
        string clientId = "";
        private void ProcessLogin(Socket client, string clientId, string result)
        {
            if (result.Trim().ToLower() == "ok")
            {
                this.clientId = clientId;
            }
            else
            {
                if (ErrorEvt != null)
                {
                    ErrorEvt("登录失败,用户名或密码不正确");
                }
            }
        }





        static ClientConnector m_ClientConnector = null;
        public static ClientConnector GetInstance()
        {
            if (m_ClientConnector == null)
            {
                m_ClientConnector = new ClientConnector();
            }
            return m_ClientConnector;
        }
        //public static int Connection()
        //{
        //}



        internal void Send(string data, MsgType type)
        {
            string msg = GetMsgType(data, type);
            try
            {
                byte[] byteData = Encoding.GetEncoding("GB2312").GetBytes(msg);
                if (m_Socket.Connected)
                {
                    Console.WriteLine("开始发送");
                    m_Socket.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), m_Socket);
                }
                else
                {
                    Console.WriteLine("未能连接服务器");
                    m_Socket.Disconnect(false);
                }

            }
            catch (Exception ex)
            {
                //MessageBox.Show("请先确认启动服务器");
                try
                {
                    if (getreceive != null)
                    {
                        getreceive.Abort();
                    }

                    //this.Close();
                    ex.GetBaseException();
                }
                catch { }
                return;

            }
            finally
            {



            }
        }

        private string GetMsgType(string data, MsgType type)
        {
            return string.Format("{0}|{1}|{2}", (int)type, this.clientId, data);
        }




        internal static void BeginAcceptData()
        {
            GetInstance().Receive();
        }
        bool ReUseScoket = false;
        internal void Close()
        {
            Console.WriteLine("发送退出请求到服务器");
            GetInstance().Exit();
            StateObject so = new StateObject();
            so.sb = new StringBuilder();
            so.workSocket = m_Socket;

            m_Socket.BeginDisconnect(ReUseScoket, new AsyncCallback(DisconnectCallBack), so);
            connectDone.WaitOne();
            if (m_Socket.Connected)
            {
                Console.WriteLine("连接没有断开 ");
            }
            else
            {
                Console.WriteLine("连接已断开  ");
            }
        }

        private void Exit()
        {
            this.Send("", MsgType.Exit);

        }

        void DisconnectCallBack(IAsyncResult ar)
        {
            Console.WriteLine("关闭连接");
            m_Socket.EndDisconnect(ar);
            connectDone.Set();
        }

        internal void SendMsg(string p)
        {
            if (this.clientId == "")
            {
                if (ErrorEvt != null)
                    ErrorEvt("请先登录");
            }
            else
            {
                Send(p, MsgType.CommonMsg);
            }
        }
    }
}
